package jp.co.jalinfotec.sxt.service;

import java.util.ArrayList;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import jp.co.jalinfotec.sxt.common.PMF;
import jp.co.jalinfotec.sxt.common.SecurityUtil;
import jp.co.jalinfotec.sxt.dto.UserDto;
import jp.co.jalinfotec.sxt.entity.UserEntity;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;

import com.google.appengine.api.datastore.Key;

@Service("UserService")
public class UserServiceImpl implements UserService {

	/** Logging  */
	private static final Log log = LogFactory.getLog(UserServiceImpl.class);
	
	/**
	 * Store user info.<br />
	 * When user exists, user info will be updated.
	 * @param bean User info.
	 * @return on success, return true
	 */
	@Override
	public boolean store(UserDto dto){
		
		// When parameter is wrong, return false
		if (dto.getId().equals(null)) return false;
		
		// Hash the password
		String hashedPassword = SecurityUtil.getHashOfSHA1(dto.getPassword());
		
		// when user exists, update.
		if (this.exist(dto.getId())){
			PersistenceManager pm =	PMF.get().getPersistenceManager();
			try{
				// Create Key
				Key key = UserEntity.createKey(dto.getId());
				// Get Entity
				UserEntity storedEntity = pm.getObjectById(UserEntity.class, key);
				// Set updating values
				storedEntity.setName(dto.getName());
				storedEntity.setPassword(hashedPassword);
				// Store
				pm.makePersistent(storedEntity);
			}catch(Exception ex){
				log.info(String.format("ID={0}, note={1}", dto.getId(), "update"));
				return false;
			}finally{
				pm.close();
			}
			return true;
		}
		
		// when user doesn't exist, register
		PersistenceManager pm =	PMF.get().getPersistenceManager();
		try{
			// Create Entity
			UserEntity storingEntity = new UserEntity();
			storingEntity.setId(dto.getId());
			storingEntity.setName(dto.getName());
			storingEntity.setPassword(hashedPassword);
			// Create And Set Key
			storingEntity.setInternalKey(UserEntity.createKey(dto.getId()));
			// Store
			pm.makePersistent(storingEntity);
		}catch(Exception ex){
			log.info(String.format("ID={0}, note={1}", dto.getId(), "register"));
			return false;
		}finally{
			pm.close();
		}	
		return true;
	}
	
	/**
	 * Delete user info.
	 * @param bean User info.
	 * @return on success, return true.
	 */
	public boolean delete(UserDto dto){
		// When not exists, return false.
		if(!this.exist(dto.getId())) return false;
		
		PersistenceManager pm =	PMF.get().getPersistenceManager();
		try{
			// Create Key
			Key key = UserEntity.createKey(dto.getId());
			// Get Entity
			UserEntity storedEntity = pm.getObjectById(UserEntity.class, key);
			// Delete
			pm.deletePersistent(storedEntity);
		}catch(Exception ex){
			log.info(String.format("ID={0}, note={1}", dto.getId(), "delete"));
			return false;
		}finally{
			pm.close();
		}
		return true;
	}
	
	/**
	 * Get user info.
	 * @param id User ID
	 * @return User info.
	 */
	public UserDto get(String id){
		UserEntity userEntity = null;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try{
			// Create Key
			Key key = UserEntity.createKey(id);
			// Get Entity
			userEntity = pm.getObjectById(UserEntity.class, key);
		}catch(Exception ex){
			log.info(String.format("ID={0}, note={1}", id, "get"));
			return null;
		}finally{
			pm.close();
		}
		return new UserDto(userEntity.getId(), userEntity.getName(), userEntity.getPassword());
	}
	
	/**
	 * Get list of users.
	 * @return list of users.
	 */
	@SuppressWarnings("unchecked")
	public List<UserDto> getAll(){
		List<UserDto> users = new ArrayList<UserDto>();
		PersistenceManager pm = PMF.get().getPersistenceManager();
		// Generate Query
		Query query = pm.newQuery(UserEntity.class);
		query.setOrdering("id asc");
		try{
			// Get All
			List<UserEntity> list = (List<UserEntity>)query.execute();
			for(UserEntity entity : list) 
				users.add(new UserDto(entity.getId(), entity.getName(), entity.getPassword()));
		}catch(Exception ex){
			log.info(String.format("ID={0}, note={1}", "(none)", "getAll"));
			return null;
		}finally{
			query.closeAll();
			pm.close();
		}
		return users;
	}
	
	/**
	 * Check if the specified user exists.
	 * @param id UserID
	 * @return when exists, return true.
	 */
	public boolean exist(String id){
		// Get All Users
		List<UserDto> list = this.getAll();
		
		// Check if the user who has the specified id exists.
		for(UserDto dto : list){
			if(dto.getId().equals(id)) return true;
		}
		return false;
	}
}